package com.yjzx.util.service.enums.file;


import com.yjzx.util.common.util.collection.CollectionUtil;
import com.yjzx.util.common.util.file.ClassLoadClassesLocal;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yjzx
 * @date 2023/5/19
 * @Description
 */
public class FileTypeFactory {
    public static final FileTypeFactory FACTORY;
    private final transient Set<Class<? extends FileType>> fileTypeClassList = new HashSet<>();
    private final transient Set<FileType> fileTypeList = new HashSet<>();
    private transient Map<String, List<FileType>> mimeTypeByFileTypeMap;
    private transient Map<String, FileType> extensionByFileTypeMap;

    static {
        FACTORY = new FileTypeFactory();
        FACTORY.init();
    }

    private FileTypeFactory() {
    }

    public Set<Class<? extends FileType>> getFileTypeClassList() {
        return Collections.unmodifiableSet(fileTypeClassList);
    }

    public Set<FileType> getFileTypeList() {
        return Collections.unmodifiableSet(fileTypeList);
    }

    public Map<String, List<FileType>> getMimeTypeByFileTypeMap() {
        return Collections.unmodifiableMap(mimeTypeByFileTypeMap);
    }

    public Map<String, FileType> getExtensionByFileTypeMap() {
        return Collections.unmodifiableMap(extensionByFileTypeMap);
    }

    private void init() {
        Class<FileType> c = FileType.class;
        //如果不是一个接口，则不做处理
        if (c.isInterface()) {
            //获得当前的包名
            String packageName = c.getPackage().getName();
            //获得当前包下以及子包下的所有类
            List<Class<? extends FileType>> allClass = ClassLoadClassesLocal.LOCAL_LOAD_CLASSES.findClassesInPackage(packageName, c);
            //添加所有类
            addAllFileTypeClass(allClass);
        }
    }

    public void addAllFileTypeClass(List<Class<? extends FileType>> aClass) {
        aClass.forEach(this::addFileTypeClass);
        FACTORY.fileTypeToMap();
    }

    private void addFileTypeClass(Class<? extends FileType> aClass) {
        try {
            if (aClass.isEnum()) {
                fileTypeClassList.add(aClass);
                List<Object> list = Arrays.asList((Object[]) aClass.getDeclaredMethod("values").invoke(aClass));
                fileTypeList.addAll(list
                        .stream().map(x -> (FileType) x).collect(Collectors.toList()));
            }
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    private void fileTypeToMap() {
        mimeTypeByFileTypeMap = CollectionUtil.toMapValueList(fileTypeList, FileType::getMimeType, Function.identity());
        extensionByFileTypeMap = CollectionUtil.toMap(false, fileTypeList, FileType::getExtension, Function.identity());
    }


    public static void main(String[] args) {
        FileTypeFactory factory = FileTypeFactory.FACTORY;
        System.out.println();
    }
}
